﻿#region using
using System;
using System.Text;
using System.IO;
using System.Xml;
using System.Collections;
using System.Collections.Generic;
using RAP.Framework.Libary.Utils;
using System.Collections.Concurrent;
using RAP.Framework.Libary.DomTemplateBuilder.Element;
using RAP.Framework.Libary.DomTemplateBuilder.Handler;
using RAP.Framework.Libary.DomTemplateBuilder.Configuration;
using RAP.Framework.Libary.DomTemplateBuilder.ContentRender;
using RAP.Framework.Libary.DomTemplateBuilder.ContentRender.Pattern;
using System.Threading;
using RAP.Framework.Libary.DomTemplateBuilder.Attributes;
using System.Reflection;
using System.Linq;
using RAP.Framework.Libary.DomTemplateBuilder.Interface;
#endregion

namespace RAP.Framework.Libary.DomTemplateBuilder
{
	/// <summary>
	/// 文档模板管理对象，单例模式
	/// </summary>
	public class DomTemplateManager : IDisposable
	{
		#region Statics
		internal static object _sycnObject = new object();

		/// <summary>
		/// 
		/// </summary>
		public static string CONFIG_SECTION_NAME = "DomTemplateManager";

		/// <summary>
		/// 临时动态模板使用的NameSpace，默认为：RAP.Framework.Libary.DomTemplateBuilder.TempTemplate，可自行修改
		/// </summary>
		public static string TEMP_TEMPLATE_NAMESPACE = "RAP.Framework.Libary.DomTemplateBuilder.TempTemplate";

		/// <summary>
		/// 将要初始化的事件
		/// </summary>
		public static event Action OnInitializing;

		/// <summary>
		/// 初始化完成的事件
		/// </summary>
		public static event Action<DomTemplateManager> OnInitialized;

		/// <summary>
		/// 调试节点事件
		/// </summary>
		public static event Action<Debugger, DebuggerHandler> OnDebuggerElement;

		private static DomTemplateManager _instance;

		/// <summary>
		/// 获取单太实例
		/// </summary>
		public static DomTemplateManager Instance
		{
			get
			{
				if ( _instance == null )
				{
					lock ( _sycnObject )
					{
						if ( _instance == null )
						{
							OnInitializing?.Invoke();

							#region 初始化代码
							ContentRenders[ "Replace" ] = new ReplacePatternRender() { Name = "Replace" };
							DefaultContentRender = ContentRenders[ "SqlText" ] = new SqlTextRender() { Name = "SqlText" };
							#endregion

							_instance = new DomTemplateManager();
							OnInitialized?.Invoke( _instance );
						}
					}
				}
				return _instance;
			}
		}

		/// <summary>
		/// 内容处理器集合
		/// </summary>
		public static IDictionary<string, IContentRender> ContentRenders = new ConcurrentDictionary<string, IContentRender>();

		/// <summary>
		/// 默认的内容处理器
		/// </summary>
		public static IContentRender DefaultContentRender = null;

		/// <summary>
		/// 默认的元素类型映射关系表
		/// </summary>
		public static IDictionary<string, Type> DefaultElementTypeMappings { get; set; } = new ConcurrentDictionary<string, Type>();

		/// <summary>
		/// 默认的Handler定义
		/// </summary>
		public static IDictionary<string, Type> DefaultHandlers { get; set; } = new ConcurrentDictionary<string, Type>();
		/// <summary>
		/// 自定义的元素类型映射
		/// </summary>
		public static IDictionary<string, Type> CustomerElementMappings { get; } = new ConcurrentDictionary<string, Type>();
		/// <summary>
		/// 自定义Handler类型映射
		/// </summary>
		public static IDictionary<string, Type> CustomerHandlers { get; } = new ConcurrentDictionary<string, Type>();

		/// <summary>
		/// 注册一个Element，该对象必须包含TagHandlerAttribute的定义
		/// </summary>
		/// <param name="element"></param>
		public static void RegisterElement( Type elementType )
		{
			var tagAttr = elementType.GetCustomAttributes<TagHandlerAttribute>( true ).FirstItem();
			if ( tagAttr == null )
			{
				throw new NullReferenceException( "被注册的Element对象必须包含TagHandlerAttribute的定义！" );
			}
			RegisterElement( tagAttr.TagName.IsNullOrEmptyValue( ( ) => elementType.Name ), elementType, tagAttr.HandlerType );
		}

		/// <summary>
		/// 注册指定TagName、ElementType和HandlerType
		/// </summary>
		/// <param name="tagName"></param>
		/// <param name="elementType"></param>
		/// <param name="handlerType"></param>
		public static void RegisterElement( string tagName, Type elementType, Type handlerType )
		{
			DefaultElementTypeMappings.Add( tagName, elementType );
			DefaultHandlers.Add( tagName, handlerType );
		}

		/// <summary>
		/// 对已存在的Element设置自定义的Handler
		/// </summary>
		/// <param name="tagName"></param>
		/// <param name="handler"></param>
		public static void RegisterElement( string tagName, Type handlerType )
		{
			if ( !DefaultElementTypeMappings.ContainsKey( tagName ) )
			{
				throw new Exception( $"指定的Tag【{tagName}】不存在！" );
			}
			DefaultHandlers[ tagName ] = handlerType;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="typeName"></param>
		/// <returns></returns>
		public static Type GetHandlerType( string typeName )
		{
			Type type = null;

			CustomerHandlers.TryGetValue( typeName, out type );
			if ( type == null )
			{
				DefaultHandlers.TryGetValue( typeName, out type );
			}
			return type;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="typeName"></param>
		/// <returns></returns>
		public static Type GetElementType( string typeName )
		{
			Type type = null;

			CustomerElementMappings.TryGetValue( typeName, out type );
			if ( type == null )
			{
				DefaultElementTypeMappings.TryGetValue( typeName, out type );
			}
			return type;
		}

		public static IContentRender GetContentRender( string key )
		{
			if ( ContentRenders.ContainsKey( key ) )
			{
				return ContentRenders[ key ];
			}
			if ( DefaultContentRender != null && DefaultContentRender.Name == key )
			{
				return DefaultContentRender;
			}
			return null;
		}

		internal static void FireDebuggerElement( Debugger ele, DebuggerHandler handler )
		{
			OnDebuggerElement?.Invoke( ele, handler );
		}
		#endregion

		#region Property
		public IDictionary<string, TemplateItem> TemplateItems { get; set; }
		public IDictionary DomTemplates { get; set; }

		private IList _pathWatchers = new ArrayList();

		#endregion

		#region Event
		/// <summary>
		/// 发生错误的事件
		/// </summary>
		public static event Action<IDictionary> OnErrorEvent;
		#endregion

		private DomTemplateManager( )
		{
			if ( _instance != null )
			{
				throw new Exception( "DomTemplateManager对象为单例模式，不能重复实例化！" );
			}
			_instance = this;
			TemplateItems = new ConcurrentDictionary<string, TemplateItem>();
			DomTemplates = new ConcurrentDictionary<string, DomTemplate>();
			Initialize();
		}

		/// <summary>
		/// 执行初始化
		/// </summary>
		private void Initialize( )
		{
			//初始化默认的Element和Handler
			var ass = Assembly.GetExecutingAssembly();
			ass.GetTypes().Where( t => t.GetInterface( nameof( IContextElement ) ) != null && !t.IsInterface && t != typeof( ElementBase ) ).Map<Type>( type =>
			{
				RegisterElement( type );
				return true;
			} );
		}

		internal void FireErrorEvent( Exception exp )
		{
			OnErrorEvent?.Invoke( exp.ToDictionary() );
		}

		/// <summary>
		/// 是否开启文件监视
		/// </summary>
		public bool EnableWatcher { get; set; }

		#region Create Functions
		/// <summary>
		/// 
		/// </summary>
		/// <param name="parent"></param>
		/// <param name="configContext"></param>
		/// <param name="section"></param>
		/// <returns></returns>
		public object Create( object parent, object configContext, XmlNode section )
		{
			EnableWatcher = section.Attributes.ToBoolean( "Watcher", false );
			Create( section );
			return this;
		}

		/// <summary>
		/// 根据XML配置路劲初始化配置
		/// </summary>
		/// <param name="configUrl"></param>
		/// <param name="enableWatcher"></param>
		/// <returns></returns>
		public DomTemplateManager Create( string configUrl, bool enableWatcher = true )
		{
			EnableWatcher = enableWatcher;
			return Create( configUrl.ReadXML().DocumentElement, enableWatcher );
		}

		/// <summary>
		/// 创建指定路径的文件系统监视
		/// </summary>
		/// <param name="section"></param>
		public DomTemplateManager Create( XmlNode section, bool enableWatcher = true )
		{
			Action<XmlNode, string, DomTemplate, bool> parseConfigure = null;
			Action<string> createWatcher = null;
			Func<XmlNode, XmlNode> parseConfigFile = null;

			#region 处理Config配置节点
			//处理Config配置节点
			parseConfigFile = ( XmlNode paramNode ) =>
			{
				string cfgPath = paramNode.Attributes.ToString( "Url" );
				if ( cfgPath.IsNullOrEmpty() )
				{
					FireErrorEvent( new NullReferenceException( "配置文件路径不能为空！" ) );
					return null;
				}
				cfgPath = cfgPath.Translator().MapPath();
				if ( !cfgPath.IsFileExists() )
				{
					FireErrorEvent( new FileNotFoundException( "未找到指定路径的配置文件【" + cfgPath + "】！", cfgPath ) );
					return null;
				}
				enableWatcher = paramNode.Attributes.ToBoolean( "Watcher", enableWatcher );
				if ( enableWatcher )
				{
					createWatcher( cfgPath );
				}
				return cfgPath.ReadXML().DocumentElement;
			};
			#endregion

			#region 处理ConfigPath配置节点
			//处理ConfigPath配置节点，如果Watcher属性为true，则开启文件夹监视，及时更新配置
			Action<XmlNode, string, DomTemplate> parseConfigPath = ( XmlNode paramNode, string nameSpace, DomTemplate domTemplate ) =>
			{
				string cfgPath = paramNode.Attributes.ToString( "Path" );
				if ( cfgPath.IsNullOrEmpty() )
				{
					FireErrorEvent( new NullReferenceException( "配置路径不能为空！" ) );
					return;
				}
				cfgPath = cfgPath.Translator().MapPath();
				if ( !cfgPath.IsPathExists() )
				{
					FireErrorEvent( new FileNotFoundException( "未找到指定路径的配置【" + cfgPath + "】！", cfgPath ) );
					return;
				}
				enableWatcher = paramNode.Attributes.ToBoolean( "Watcher", enableWatcher );
				if ( enableWatcher )
				{
					createWatcher( cfgPath );
				}
				cfgPath.EachAllFiles( ( FileInfo file ) =>
			   {
				   parseConfigure( file.FullName.ReadXML().DocumentElement, nameSpace, domTemplate, true );
				   return true;
			   }, "*.config" );
			};
			#endregion

			#region 创建文件、文件夹监视
			//创建文件夹监视
			createWatcher = ( path ) =>
			{
				if ( path.IsNullOrEmpty() )
				{
					FireErrorEvent( new NullReferenceException( "文件或文件夹路径不能为空！" ) );
					return;
				}
				//如果是文件夹，则返回*.config，否则返回文件路径
				string filter = null;
				if ( path.IsPathExists() )
				{
					filter = "*.config";
				}
				else if ( path.IsFileExists() )
				{
					FileInfo fInfo = path.FileInfo();
					filter = fInfo.Name;
					path = fInfo.DirectoryName;
				}
				else
				{
					path = null;
				}
				if ( path.IsNotNullOrEmpty() )
				{
					//监视文件、文件夹
					IDictionary watcherInfo = FileSystemWatcherUtils.RegisterWatcher( path
						, filter
						, NotifyFilters.LastWrite | NotifyFilters.CreationTime | NotifyFilters.Size
						, ( watcher, eventArgs ) =>
					{
						if ( !EnableWatcher ) return;
            try
						{
							switch ( eventArgs.ChangeType )
							{
								case WatcherChangeTypes.Changed:
								case WatcherChangeTypes.Created:
									if ( eventArgs.FullPath.IsFileExists() )
									{
                    //如果创建或变更的是文件
                    Debug.Info($"Template File Changed: {eventArgs.FullPath}");
                    parseConfigure( eventArgs.FullPath.ReadXML().DocumentElement, null, null, false );
									}
									else if ( eventArgs.FullPath.IsPathExists() )
									{
										//如果创建了子文件夹
                    Debug.Info($"Template Directory Changed: {eventArgs.FullPath}");
										eventArgs.FullPath.EachAllFiles( ( FileInfo file ) =>
									   {
										   parseConfigure( file.FullName.ReadXML().DocumentElement, null, null, false );
										   return true;
									   }, "*.config" );
									}
									break;
							}
						}
						catch ( Exception e )
						{
							FireErrorEvent( new FileNotFoundException( "加载指定的模板配置文件时发生异常！", eventArgs.FullPath.UnMapPath(), e ) );
						}
						finally { }
					} );
					_pathWatchers.Add( watcherInfo );
				}
				else
				{
					FireErrorEvent( new DirectoryNotFoundException( "指定的路径【" + path + "】不存在！" ) );
					return;
				}
			};
			#endregion

			#region 处理配置内容节点
			//处理配置内容节点
			parseConfigure = ( XmlNode paramNode, string nameSpace, DomTemplate domTemplate, bool checkSameKey ) =>
			{
				if ( paramNode == null || paramNode.NodeType != XmlNodeType.Element )
				{
					//如果不是Element元素，则直接跳过
					return;
				}

				switch ( paramNode.Name )
				{
					case "DomTemplate":
						nameSpace = paramNode.Attributes.ToString( "NameSpace", nameSpace );
						domTemplate = CreateDomTemplate( nameSpace, paramNode );
						break;

					case "CustomerHandlers":
						CreateCustomerHandler( paramNode, domTemplate );
						return;

					case "CustomerElements":
						CreateElementTypeMapping( paramNode, domTemplate );
						return;

					case "ContentRenders":
						CreateContentRender( paramNode, domTemplate );
						break;

					case "DefaultContentRender":
						CreateDefaultContentRender( paramNode, domTemplate );
						break;

					case "Template":
						var tplItem = CreateTemplateItem( paramNode, domTemplate, checkSameKey );
						TemplateItems[ tplItem.FullName ] = tplItem;
						return;

					case "Config":
						parseConfigure( parseConfigFile( paramNode ), nameSpace, domTemplate, checkSameKey );
						break;

					case "ConfigPath":
						parseConfigPath( paramNode, nameSpace, domTemplate );
						break;
				}
				foreach ( XmlNode node in paramNode.ChildNodes )
				{
					parseConfigure( node, nameSpace, domTemplate, checkSameKey );
				}
			};
			#endregion

			parseConfigure( section, null, null, true );
			return this;
		}

		/// <summary>
		/// 创建一个指定类型的内容处理器
		/// </summary>
		/// <param name="node"></param>
		protected void CreateContentRender( XmlNode node, DomTemplate domTemplate )
		{
			Action<XmlNode> doAdd = ( XmlNode cfgNode ) =>
			{
				string typeName = cfgNode.Attributes.ToString( "Type" );
				if ( !string.IsNullOrEmpty( typeName ) )
				{
					Type type = Type.GetType( typeName );
					IContentRender render = Activator.CreateInstance( type ) as IContentRender;
					if ( render != null )
					{
						string name = cfgNode.Attributes.ToString( "Name", type.Name );
						bool enable = cfgNode.Attributes.ToBoolean( "Enable", true );
						render.Name = name;
						if ( domTemplate == null )
						{
							ContentRenders.Add( name, render );
						}
						else
						{
							domTemplate.ContentRender = render;
						}
					}
				}
			};

			Action doClear = ( ) =>
			{
				ContentRenders.Clear();
			};

			Action<XmlNode> doRemove = ( XmlNode removeNode ) =>
			{
				string name = removeNode.Attributes.ToString( "Name" );
				if ( !string.IsNullOrEmpty( name ) )
				{
					ContentRenders.Remove( name );
				}
				else
				{
					FireErrorEvent( new NullReferenceException( "要删除的ContentRender名称不能为空！" ) );
					return;
				}
			};

			foreach ( XmlNode child in node.ChildNodes )
			{
				if ( child.NodeType != XmlNodeType.Element )
				{
					continue;
				}
				switch ( child.Name )
				{
					case "Clear":
						doClear();
						break;

					case "Remove":
						doRemove( child );
						break;

					case "Add":
						doAdd( child );
						break;
				}
			}

		}


		/// <summary>
		/// 配置指定类型的默认内容处理器
		/// </summary>
		/// <param name="node"></param>
		protected void CreateDefaultContentRender( XmlNode node, DomTemplate domTemplate )
		{
			string typeName = node.Attributes.ToString( "Type" );
			if ( typeName.IsNotNullOrEmpty() )
			{
				Type type = Type.GetType( typeName );
				IContentRender render = Activator.CreateInstance( type ) as IContentRender;
				if ( render != null )
				{
					string name = node.Attributes.ToString( "Name", type.Name );
					bool enable = node.Attributes.ToBoolean( "Enable", true );
					render.Name = name;
					if ( domTemplate == null )
					{
						DefaultContentRender = render;
					}
					else
					{
						domTemplate.ContentRender = render;
					}
				}
			}
		}

		/// <summary>
		/// 根据配置创建XML模板对象
		/// </summary>
		/// <param name="node"></param>
		protected DomTemplate CreateDomTemplate( string nameSpace, XmlNode node = null )
		{
			return DomTemplates.ToObject( nameSpace, ( ) =>
			{
				var domTpl = new DomTemplate { TemplateManager = this };
				domTpl.NameSpace = nameSpace;
				if ( node != null )
				{
					domTpl[ Consts.CONTENT_RENDER_FIELD ] = node.Attributes.ToString( Consts.CONTENT_RENDER_FIELD );
				}
				DomTemplates.Add( nameSpace, domTpl );
				return domTpl;
			} );
		}

		/// <summary>
		/// 创建一个配置节点Template
		/// </summary>
		/// <param name="node"></param>
		/// <param name="domTemplate"></param>
		/// <returns></returns>
		protected TemplateItem CreateTemplateItem( XmlNode section, DomTemplate domTemplate, bool checkSameKey = true, TemplateItem parent = null )
		{
			TemplateItem item = new TemplateItem() { ParentTemplate = parent };
			TemplateItem.Create( section, item, domTemplate );
			var fullName = item.FullName;
			if ( checkSameKey && TemplateItems.ContainsKey( fullName ) )
			{
				FireErrorEvent( new Exception( "名称为：[" + fullName + "]的配置已存在！URL:" + section.OwnerDocument.BaseURI ) );
				return null;
			}
			return item;
		}

		/// <summary>
		/// 创建节点的自定义Handler
		/// </summary>
		/// <param name="node"></param>
		protected void CreateCustomerHandler( XmlNode node, DomTemplate domTemplate = null )
		{
			Action<XmlNode> doAdd = ( XmlNode cfgNode ) =>
			{
				string name = cfgNode.Attributes.ToString( "Name" );
				string typeFullName = cfgNode.Attributes.ToString( "TypeName" );
				Type type = Type.GetType( typeFullName );
				if ( domTemplate == null )
				{
					CustomerHandlers.Add( name, type );
				}
				else
				{
					domTemplate.CustomerHandlers.Add( name, type );
				}
			};

			Action doClear = ( ) =>
			{
				if ( domTemplate == null )
				{
					CustomerHandlers.Clear();
				}
				else
				{
					domTemplate.CustomerHandlers.Clear();
				}
			};

			Action<XmlNode> doRemove = ( XmlNode removeNode ) =>
			{
				string name = removeNode.Attributes.ToString( "Name" );
				if ( !string.IsNullOrEmpty( name ) )
				{
					CustomerHandlers.Remove( name );
				}
				else
				{
					FireErrorEvent( new NullReferenceException( "要删除的Handler名称不能为空！" ) );
					return;
				}
			};

			foreach ( XmlNode child in node.ChildNodes )
			{
				if ( child.NodeType != XmlNodeType.Element )
				{
					continue;
				}
				switch ( child.Name )
				{
					case "Clear":
						doClear();
						break;

					case "Remove":
						doRemove( child );
						break;

					case "Add":
						doAdd( child );
						break;
				}
			}
		}

		/// <summary>
		/// 创建节点对象映射
		/// </summary>
		/// <param name="node"></param>
		protected void CreateElementTypeMapping( XmlNode node, DomTemplate domTemplate = null )
		{
			Action<XmlNode> doAdd = ( XmlNode cfgNode ) =>
			{
				string nodeName = cfgNode.Attributes.ToString( "Name" );
				string nodeTypeFullName = cfgNode.Attributes.ToString( "TypeName" );
				Type nodeType = Type.GetType( nodeTypeFullName );
				if ( domTemplate == null )
				{
					CustomerElementMappings.Add( nodeName, nodeType );
				}
				else
				{
					domTemplate.CustomerElementMappings.Add( nodeName, nodeType );
				}
			};

			Action doClear = ( ) =>
			{
				if ( domTemplate == null )
				{
					CustomerElementMappings.Clear();
				}
				else
				{
					domTemplate.CustomerElementMappings.Clear();
				}
			};

			Action<XmlNode> doRemove = ( XmlNode removeNode ) =>
			{
				string name = removeNode.Attributes.ToString( "Name" );
				if ( !string.IsNullOrEmpty( name ) )
				{
					if ( domTemplate == null )
					{
						CustomerElementMappings.Remove( name );
					}
					else
					{
						domTemplate.CustomerElementMappings.Remove( name );
					}
				}
				else
				{
					FireErrorEvent( new NullReferenceException( "要删除的Element名称不能为空！" ) );
					return;
				}
			};

			foreach ( XmlNode child in node.ChildNodes )
			{
				if ( child.NodeType != XmlNodeType.Element )
				{
					continue;
				}
				switch ( child.Name )
				{
					case "Clear":
						doClear();
						break;

					case "Remove":
						doRemove( child );
						break;

					case "Add":
						doAdd( child );
						break;
				}
			}
		}
		#endregion

		/// <summary>
		/// 获取指定fullname的模板项
		/// </summary>
		/// <param name="fullName"></param>
		/// <returns></returns>
		public TemplateItem GetTemplateItem( string fullName )
		{
			if ( !TemplateItems.TryGetValue( fullName, out TemplateItem tpl ) )
			{
				var idx = fullName.LastIndexOf( '.' );
				if ( idx > 0 )
				{
					var parentTplName = fullName.Substring( 0, idx );
					var childTplName = fullName.Substring( idx + 1 );
					var parentTpl = GetTemplateItem( parentTplName );
					if ( parentTpl != null )
					{
						if ( parentTpl.ChildTemplates.TryGetValue( childTplName, out tpl ) )
						{
							return tpl;
						}
						else
						{
							return null;
						}
					}
				}
			}
			return tpl;
		}

		/// <summary>
		/// 检测指定Id的模板是否存在
		/// </summary>
		/// <param name="fullName"></param>
		/// <returns></returns>
		public bool HasTemplate( string fullName )
		{
			return GetTemplateItem( fullName ) != null;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="tpl"></param>
		/// <param name="paramObject"></param>
		/// <param name="context"></param>
		/// <returns></returns>
		public string RunTemplate( TemplateItem tpl, object paramObject, ITemplateRenderContext context = null )
		{
			return tpl.DoRender( paramObject, context );
		}

		/// <summary>
		/// 格式化指定完全名称的模板
		/// </summary>
		/// <param name="fullName"></param>
		/// <param name="paramObject"></param>
		/// <returns></returns>
		public string RunTemplate( string fullName, object paramObject, ITemplateRenderContext context = null )
		{
			if ( fullName.IsNullOrEmpty() )
			{
				return null;
			}
			context = context.IsNullValue( ( ) =>
			{
				return new TemplateRenderContext();
			} );
			var names = fullName.Split( ',' );
			var sb = new StringBuilder();
			foreach ( var name in names )
			{
				var tplName = name.Trim();
				if ( string.IsNullOrEmpty( tplName ) )
				{
					throw new NullReferenceException( "名称不能为空！" );
				}
				var tplItem = GetTemplateItem( tplName );

				if ( tplItem == null )
				{
					throw new NullReferenceException( string.Format( "Cannot find the name '{0}' template.", fullName ) );
				}
				var content = tplItem.DoRender( paramObject, context );
				sb.AppendLine( string.IsNullOrEmpty( content ) ? "" : content.Trim() );
			}
			return sb.ToString();
		}

		/// <summary>
		/// 格式化简单字符串
		/// </summary>
		/// <param name="exp"></param>
		/// <param name="paramObject"></param>
		/// <param name="context"></param>
		/// <returns></returns>
		public string FormatString( string exp, object paramObject, ITemplateRenderContext context = null )
		{
			var st = new SimpleText();
			st.Content = exp;
			var writer = new StringBuilder();
			context = context.IsNullValue( ( ) =>
			{
				return new TemplateRenderContext();
			} );
			st.Handler = new SimpleTextHandler();
			st.Handler.Element = st;
			st.Handler.DoRender( writer, paramObject, paramObject, context );
			return writer.ToString();
		}

		private int _TEMP_TEMPLATE_ID = 0;

		/// <summary>
		/// 将指定的模板字符串编译为模板对象
		/// </summary>
		/// <param name="tplExp">模板表达式字符串</param>
		/// <returns></returns>
		public TemplateItem CompileTemplate( string tplExp, string nameSpace = null, string tplName = null, TemplateItem parent = null )
		{
			if ( tplName.IsNullOrEmpty() )
			{
				Interlocked.Increment( ref _TEMP_TEMPLATE_ID );
				tplName = $"Temp_{DateTime.Now.ToDateString( "yyyyMMdd" )}_{_TEMP_TEMPLATE_ID}";
			}
			if ( nameSpace.IsNullOrEmpty() )
			{
				nameSpace = parent != null ? parent.DomTemplate.NameSpace : TEMP_TEMPLATE_NAMESPACE;
			}
			var docTpl = new XmlDocument();
			var tplSection = docTpl.CreateElement( "Template" ).AddAttribute( "Name", tplName );
			tplSection.InnerXml = tplExp;
			return CreateTemplateItem( tplSection, CreateDomTemplate( nameSpace ), false, parent );
		}

		/// <summary>
		/// 动态编译模板字符串并运行
		/// </summary>
		/// <returns></returns>
		public string RunTemplateString( string tplExp, object paramObject, ITemplateRenderContext context = null )
		{
			var result = string.Empty;
			try
			{
				var tpl = CompileTemplate( tplExp );
				result = RunTemplate( tpl, paramObject, context );
			}
			catch ( Exception ex )
			{
				throw ex;
			}
			return result;
		}

		internal string RunTemplate( string fullName, object rootParamObject, object parentParamObject, ITemplateRenderContext context )
		{
			var tplItem = GetTemplateItem( fullName );

			if ( tplItem == null )
			{
				throw new NullReferenceException( string.Format( "Error!Cannot find the name '{0}' template.", fullName ) );
			}
			return TemplateItem.DoRender( tplItem, rootParamObject, parentParamObject, context );
		}

		/// <summary>
		/// 移除指定路径配置文件中的配置项
		/// </summary>
		/// <param name="configFile"></param>
		public void RemoveTemplate( FileInfo configFile )
		{
			var configFilePath = configFile.FullName;
			foreach ( var key in TemplateItems.Keys )
			{
				TemplateItems.TryGetValue( key, out var tplItem );
				if ( tplItem != null && tplItem.OwnerFile.FullName == configFilePath )
				{
					TemplateItems.Remove( key );
				}
			}
		}

		/// <summary>
		/// 移除指定完全名称的模板
		/// </summary>
		/// <param name="key"></param>
		public void RemoveTemplate( string fullName )
		{
			if ( TemplateItems.ContainsKey( fullName ) )
			{
				TemplateItems.TryGetValue( fullName, out var tpl );
				RemoveTemplate( tpl );
			}
		}

		/// <summary>
		/// 移除指定的模板
		/// </summary>
		/// <param name="tpl"></param>
		public void RemoveTemplate( TemplateItem tpl )
		{
			if ( tpl == null )
			{
				return;
			}
			TemplateItems.Remove( tpl.FullName );
			tpl.Dispose();
		}

		public void Dispose( )
		{
			DefaultHandlers.Clear();
			CustomerHandlers.Clear();
			CustomerElementMappings.Clear();
			DefaultElementTypeMappings.Clear();
			ExpressionUtils.FieldNameRenders.Clear();
			foreach ( IDisposable tpl in TemplateItems.Values )
			{
				tpl.Dispose();
			}

			foreach ( IDictionary watcherInfo in _pathWatchers )
			{
				watcherInfo.ToObject<IDisposable>( FileSystemWatcherUtils.WATCHER_FIELD ).Dispose();
			}

			TemplateItems.Clear();
			TemplateItems = null;
			DomTemplates.Clear();
			DomTemplates = null;
			_pathWatchers.Clear();
			_pathWatchers = null;
			DefaultElementTypeMappings = null;
			DefaultHandlers = null;
			_instance = null;
		}
	}
}